use std::any::Any;

use async_trait::async_trait;

use common_base::prelude::*;

use crate::{
    data::{DataModel, DataObject, ParamObject, ResponseObject},
    service_engine::service_context::ServiceContext,
    ServiceContextBase,
};

pub type ServiceContextBuilderCreator =
    unsafe extern "C" fn() -> *mut Box<dyn ServiceContextBuilder>;

#[async_trait]
pub trait ServiceContextBuilder: Any + Send + Sync {
    async fn new_context(&self, srv_ctx_base: ServiceContextBase) -> Box<dyn ServiceContext>;

    async fn create_response(
        &self,
        srv_ctx: &mut dyn ServiceContext,
    ) -> Result<Option<Box<dyn DataModel>>>;

    async fn finish_context(&self, srv_ctx: &mut dyn ServiceContext) -> Result<()>;

    fn get_prepare_service_params(
        &self,
        _: &dyn ServiceContext,
    ) -> Option<(
        ParamObject,
        Option<DataObject>, /*customObject, addonObject */
    )> {
        None
    }

    async fn process_prepare_service_response(
        &self,
        _: &mut dyn ServiceContext,
        _: ResponseObject,
    ) -> Result<()> {
        // nothing to do
        Ok(())
    }

    fn get_finish_service_params(
        &self,
        _: &dyn ServiceContext,
    ) -> Option<(
        ParamObject,
        Option<DataObject>, /*customObject, addonObject */
    )> {
        None
    }

    async fn process_finish_service_response(
        &self,
        _: &mut dyn ServiceContext,
        _: ResponseObject,
    ) -> Result<()> {
        // nothing to do
        Ok(())
    }
}
